package main

import "fmt"

func test(fn func() int) int {
	return fn()
}

// 定义函数类型。
type FormatFunc func(s string, x, y int) string

func format(fn FormatFunc, s string, x, y int) string {
	return fn(s, x, y)
}

/* 定义相互交换值的函数 */
func swap(x, y *int) {
	var temp int

	temp = *x /* 保存 x 的值 */
	*x = *y   /* 将 y 值赋给 x */
	*y = temp /* 将 temp 值赋给 y*/

}

func add(a, b int) (d int) {
	d = a + b
	return
}

func calc(a, b int) (avg int, sum int) {
	sum = a + b
	avg = (a + b) / 2

	return
}

func test1() (int, int) {
	return 633, 2
}

func main() {
	// s1 := test(func() int { return 100 }) // 直接将匿名函数当参数。

	// s2 := format(func(s string, x, y int) string {
	// 	return fmt.Sprintf(s, x, y)
	// }, "%d, %d", 10, 20)

	// println(s1, s2)

	// var a, b int = 1, 2
	// /*
	//    调用 swap() 函数
	//    &a 指向 a 指针，a 变量的地址
	//    &b 指向 b 指针，b 变量的地址
	// */
	// swap(&a, &b)

	// fmt.Println(a, b)

	// var a, b int = 1, 2
	// c := add(a, b)
	// sum, avg := calc(a, b)
	// fmt.Println(a, b, c, sum, avg)

	// s := make([]int, 2)
	// s = test1() // Error: multiple-value test() in single-value context

	// x, y := test1()
	// println(x, y)

	// getSqrt := func(a float64) float64 {
	// 	return math.Sqrt(a)
	// }
	// fmt.Println(getSqrt(4))

	// --- function collection ---
	// fns := [](func(x int) int){
	// 	func(x int) int { return x + 1 },
	// 	func(x int) int { return x + 2 },
	// }
	// println(fns[0](100), fns[1](120))

	// d := struct {
	// 	fn func() string
	// }{
	// 	fn: func() string { return "Hello, World!" },
	// }
	// println(d.fn())

	// --- channel of function ---
	// fc := make(chan func() string, 2)
	// fc <- func() string { return "Hello, World!" }
	// println((<-fc)())

	// f := test2()
	// f()

	// tmp1 := add1(10)
	// fmt.Println(tmp1(1), tmp1(2))
	// // 此时tmp1和tmp2不是一个实体了
	// tmp2 := add1(100)
	// fmt.Println(tmp2(1), tmp2(2))

	// f1, f2 := test01(10)
	// // base一直是没有消
	// fmt.Println(f1(1), f2(2))
	// // 此时base是9
	// fmt.Println(f1(3), f2(4))

	// var i int = 7
	// fmt.Printf("Factorial of %d is %d\n", i, factorial(i))

	var whatever [5]struct{}

	for i := range whatever {
		defer fmt.Println(i)
	}

}

func factorial(i int) int {
	if i <= 1 {
		return 1
	}
	return i * factorial(i-1)
}

// 返回2个函数类型的返回值
func test01(base int) (func(int) int, func(int) int) {
	// 定义2个函数，并返回
	// 相加
	add := func(i int) int {
		base += i
		return base
	}
	// 相减
	sub := func(i int) int {
		base -= i
		return base
	}
	// 返回
	return add, sub
}

// 外部引用函数参数局部变量
func add1(base int) func(int) int {
	return func(i int) int {
		base += i
		return base
	}
}

func test2() func() {
	x := 100
	fmt.Printf("num1: x (%p) = %d\n", &x, x)

	return func() {
		fmt.Printf("num2: x (%p) = %d\n", &x, x)
	}
}
